package controllers;

import models.User;
import models.User.ProfileTypes;

import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Date;

import controllers.Secure.Security;
import play.Play;
import play.mvc.*;
import play.data.validation.*;
import play.libs.*;
import play.utils.*;

public class MySecure extends Controller{

	@Before(unless={"login", "authenticate", "logout"})
    static void checkAccess() throws Throwable {
		if(!session.contains("username")) {
            flash.put("url", "GET".equals(request.method) ? request.url : Play.ctxPath + "/"); // seems a good default
            System.out.println("Hello");
            UserManager.index();
        }
        // Checks
        Check check = getActionAnnotation(Check.class);
        if(check != null) {
            check(check);
        }
        check = getControllerInheritedAnnotation(Check.class);
        if(check != null) {
            check(check);
        }
	}
	private static void check(Check check) throws Throwable {
        for(String profile : check.value()) {
            boolean hasProfile = (Boolean)Security.invoke("check", profile);
            if(!hasProfile) {
                Security.invoke("onCheckFailed", profile);
            }
        }
    }
    public static void authenticate(@Required String username, String password, boolean remember, int x) throws Throwable {
        // Check tokens
        Boolean allowed = false;
        try {
        	
            // This is the deprecated method name
            allowed = (Boolean)MySecure.Security.invoke("authentify", username, password);
        } catch (UnsupportedOperationException e ) {
            // This is the official method name
            allowed = (Boolean)MySecure.Security.invoke("authenticate", username, password);
        }
        if(validation.hasErrors() || !allowed) {
            flash.keep("url");
            flash.error("secure.error");
            params.flash();
            UserManager.index();
        }
        // Mark user as connected
        session.put("username", username);
        // Remember if needed
        if(remember) {
            Date expiration = new Date();
            String duration = "30d";  // maybe make this override-able 
            expiration.setTime(expiration.getTime() + Time.parseDuration(duration));
            response.setCookie("rememberme", Crypto.sign(username + "-" + expiration.getTime()) + "-" + username + "-" + expiration.getTime(), duration);

        }
        // Redirect to the original URL (or /)
        Application.home();
    }

    public static void logout() throws Throwable {
        Security.invoke("onDisconnect");
        session.clear();
        response.removeCookie("rememberme");
        Security.invoke("onDisconnected");
        flash.success("secure.logout");
        UserManager.index();
    }

    public static class Security extends Secure.Security {
    	
        public static boolean authenticate(String username, String password) {
        	return User.connect(username, password) != null;
        }
        public static Object invoke(String m, Object... args) throws Throwable {

            try {
                return Java.invokeChildOrStatic(MySecure.Security.class, m, args);       
            } catch(InvocationTargetException e) {
                throw e.getTargetException();
            }
        }
        static boolean check(String profile) {
        
        	ProfileTypes passedType = ProfileTypes.valueOf(profile);
        	User currentUser = User.find("byEmail", connected()).<User>first();
        	if((passedType==null)||(currentUser==null))
        		return false;
        	ProfileTypes userType =  currentUser.profileType;    	
        	switch (passedType) {
    		case NormalUser:
    			return true;
    		case PrivilgedUser:
    			return((userType == ProfileTypes.PrivilgedUser)||(userType == ProfileTypes.Administrator));
    		case Administrator:
    			return (userType == ProfileTypes.Administrator);
    		default:
    			return false;
    		}
            
        }
        
    }
    
}
